using System;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using Prism.Common;
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Services.Dialogs;
using PrismPractice.Const;

namespace PrismPractice.Core.Prism
{
	/// <summary>
	/// 修改版的 DialogService。弹窗时支持通过参数传递 DataContext（key 为 "vm"）。
	/// </summary>
	public class MyDialogService : DialogService
	{
		private readonly IContainerExtension _containerExtension;

		public MyDialogService(IContainerExtension containerExtension) : base(containerExtension)
		{
			_containerExtension = containerExtension;
		}

		/// <inheritdoc />
		protected override void ConfigureDialogWindowContent(string dialogName, IDialogWindow window, IDialogParameters parameters)
		{
			var content = _containerExtension.Resolve<object>(dialogName);
			if (!(content is FrameworkElement dialogContent))
				throw new NullReferenceException("A dialog's content must be a FrameworkElement");

			//修改点：支持通过参数传递 DataContext（key 为 "vm"）、DataContext 为空才自动装配；
			bool hasVm = parameters.TryGetValue<IDialogAware>(Keys.MY_DIALOG_SERVICE_PARA_VM_KEY, out IDialogAware vm);
			if (hasVm && vm != null)
			{
				dialogContent.DataContext = vm;
			}

			if (dialogContent.DataContext == null)
			{
				//MvvmHelpers.AutowireViewModel(dialogContent); //提示不存在这个方法，所以将其拷贝出来直接使用，后续存在了的话可以改回去。
				AutowireViewModel(dialogContent);
			}

			if (!(dialogContent.DataContext is IDialogAware viewModel))
				throw new NullReferenceException("A dialog's ViewModel must implement the IDialogAware interface");

			ConfigureDialogWindowProperties(window, dialogContent, viewModel);

			MvvmHelpers.ViewAndViewModelAction<IDialogAware>(viewModel, d => d.OnDialogOpened(parameters));
		}

		/// <inheritdoc />
		protected override void ConfigureDialogWindowProperties(IDialogWindow window, FrameworkElement dialogContent, IDialogAware viewModel)
		{
			var windowStyle = Dialog.GetWindowStyle(dialogContent);
			if (windowStyle != null)
				window.Style = windowStyle;

			window.Content = dialogContent;
			window.DataContext = viewModel; //we want the host window and the dialog to share the same data context

			if (window.Owner == null)
			{
				//修改点：没有激活窗口时，使用主窗口作为 Owner
				window.Owner = Application.Current?.Windows.OfType<Window>().FirstOrDefault(x => x.IsActive) ?? Application.Current?.MainWindow;
			}
		}

		/// <summary>
		/// Sets the AutoWireViewModel property to true for the <paramref name="viewObj"/>.
		/// </summary>
		/// <remarks>
		/// The AutoWireViewModel property will only be set to true if the view
		/// is a <see cref="FrameworkElement"/>, the DataContext of the view is null, and
		/// the AutoWireViewModel property of the view is not false.
		/// </remarks>
		/// <param name="viewObj">The View</param>
		[EditorBrowsable(EditorBrowsableState.Never)]
		public static void AutowireViewModel(object viewObj)
		{
			if (viewObj is FrameworkElement view && view.DataContext is null)
			{
				bool? isAutoWire = ViewModelLocator.GetAutoWireViewModel(view);
				if (isAutoWire == false)
					return;

				if (isAutoWire == null)
				{
					ViewModelLocator.SetAutoWireViewModel(view, true);
				}
				else
				{
					//如果 AutoWireViewModel 已经设置为 true，但是 DataCont 还是为null，可能哪里出了问题；则先将其设置为 false，再重新设置为 true，重新触发装配。
					ViewModelLocator.SetAutoWireViewModel(view, false);
					ViewModelLocator.SetAutoWireViewModel(view, true);
				}
			}
		}
	}
}
